package org.study.stream;

import com.google.common.collect.Lists;

import java.util.*;
import java.util.stream.Collectors;

/**
 * parallelStream() 示例
 * 参考 http://www.jnnr.cn/a/15154.html
 *
 * @author Administrator
 * @date 2022-12-30
 */
public class StreamTest07 {
    public static void main(String[] args) throws InterruptedException {
        int num = 10000;
        // testWithBug(num);
        test01(num);
        test02(num);
        test03(num);
        test04(num);
    }

    public static void testWithBug(int num) throws InterruptedException {
        List<Integer> list1 = Lists.newArrayList();
        for (int i = 0; i < num; i++) {
            list1.add(i);
        }
        // 问题：使用 parallelStream() 并行流，每次请求 list 数据集合变化
        // parallelStream() 是并行流，当使用时会出来 list2 中 add 值的变化，是因为 ArrayList 是线程不安全问题；
        // 解决方法1：将 parallelStream() 换成 stream() 或者直接使用 list.forEach()
        // 解决方法2：使用 map 转成新对象，然后再转成 list
        List<Integer> list2 = Lists.newArrayList();
        list1.parallelStream().forEach(e ->
                list2.add(e)
        );
        System.out.println("【有bug】list1.size()=" + list1.size() + "，list2.size()=" + list2.size());
    }


    public static void test01(int num) throws InterruptedException {
        List<Integer> list1 = Lists.newArrayList();
        for (int i = 0; i < num; i++) {
            list1.add(i);
        }
        List<Integer> list2 = Collections.synchronizedList(new ArrayList<>());
        list1.parallelStream().forEach(e ->
                list2.add(e)
        );
        System.out.println("【使用线程安全的List】list1.size()=" + list1.size() + "，list2.size()=" + list2.size());
    }

    public static void test02(int num) {
        List<Integer> list1 = Lists.newArrayList();
        for (int i = 0; i < num; i++) {
            list1.add(i);
        }
        List<Integer> list2 = Lists.newArrayList();
        list1.stream().forEach(e -> list2.add(e));
        System.out.println("【使用stream()】list1.size()=" + list1.size() + "，list2.size()=" + list2.size());
    }

    public static void test03(int num) {
        List<Integer> list1 = Lists.newArrayList();
        for (int i = 0; i < num; i++) {
            list1.add(i);
        }
        List<Integer> list2 = Lists.newArrayList();
        list1.forEach(e -> list2.add(e));
        System.out.println("【使用forEach()】list1.size()=" + list1.size() + "，list2.size()=" + list2.size());
    }

    public static void test04(int num) {
        List<Integer> list1 = Lists.newArrayList();
        for (int i = 0; i < num; i++) {
            list1.add(i);
        }
        List<String> list2 = list1.parallelStream().map(a -> a.toString()).collect(Collectors.toList());
        System.out.println("【使用map()】list1.size()=" + list1.size() + "，list2.size()=" + list2.size());
    }
}
